<?php

namespace App\Http\Controllers;

use App\Events\ClickLogEvent;
use App\Jobs\AddIPWebCustomer;
use App\Models\ClickLog;
use App\Models\Config;
use App\Models\DistributorUser;
use App\Models\ProxyUser;
use App\Models\StaticProxyDetail;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;

class UserController extends Controller
{
    /**
     * 登录
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request)
    {
        $validator = Validator::make($request->all(),
            [
                'email' => 'required|email|exists:users',
                'password' => 'required',
                'captcha_key' => 'required',
                'captcha' => 'required'
            ]
        );
        if ($validator->fails()) {
            return response()->json([
                'errcode' => -1,
                'message' => $validator->errors()->first(),
            ]);
        }

        $captcha_key = $request->input('captcha_key');
        $input_captcha = $request->input('captcha');
        $captcha = Cache::get($captcha_key);

        if (!$captcha) {
            return response()->json([
                'errcode' => -1,
                'message' => __('message.user.login.captcha_expired')
            ]);
        }

        if (strtolower($input_captcha) != strtolower($captcha)) {
            return response()->json([
                'errcode' => -1,
                'message' => __('message.user.login.captcha_wrong')
            ]);
        }
        $user = User::where('email', $request->email)->first();
        if (!Hash::check($request->password, $user->password)) {
            return response()->json([
                'errcode' => -1,
                'message' => __('message.user.login.password_wrong')
            ]);
        }

        Cache::forget($captcha_key);
        $api_token = hash_hmac('sha256', Str::random(64), env('APP_KEY'));
        $user->api_token = $api_token;
        $user->api_token_expires_at = Carbon::now(env('APP_TIMEZONE'))->addHours(env('TOKEN_EXPIRES', 8));
        $user->save();

        $ip = $request->header('X-Real-IP') ?? $request->ip();
        $userAgent = $request->header('User-Agent');
        $isMobileDevice = preg_match('/(android|iphone|ipod|blackberry|windows phone)/i', $userAgent);

        $clickLog = ClickLog::create([
            'user_id' => $user->id,
            'ip' => $ip,
            'event_type' => 'login',
            'is_mobile' => (bool)$isMobileDevice,
            'user_agent' => $userAgent,
            'create_day' => date('Y-m-d'),
        ]);
        event(new ClickLogEvent($clickLog));

        return response()->json([
            'errcode' => 0,
            'message' => __('message.user.login.success'),
            'token' => $api_token
        ]);
    }

    private function generateUserId(): int
    {
        for ($i = 1; $i <= 10; $i++) {
            $user_id = rand(100000, 999999);
            $exist = User::where('id', $user_id)->exists();
            if (!$exist) {
                return $user_id;
            }
        }
        return $user_id;
    }

    /**
     * 注册
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function register(Request $request)
    {
        $validator = Validator::make($request->all(),
            [
                'email' => 'required|email|unique:users',
                'password' => 'required|confirmed',
                'password_confirmation' => 'required|same:password',
                'email_code' => 'required'
            ]
        );
        if ($validator->fails()) {
            return response()->json([
                'errcode' => -1,
                'message' => $validator->errors()->first(),
            ]);
        }

        $input_code = $request->input('email_code');
        $cache_key = 'register:verification:code:' . $request->email;
        $code = Cache::get($cache_key);

        if (!$code) {
            return response()->json([
                'errcode' => -1,
                'message' => __('message.user.register.email_code_expired')
            ]);
        }

        if ($input_code != $code) {
            return response()->json([
                'errcode' => -1,
                'message' => __('message.user.register.email_code_wrong')
            ]);
        }

        if (!empty($request->invite_code)) {
            $invite_userid = DistributorUser::where('invite_code', $request->invite_code)->value('user_id');
        }

        $user_id = $this->generateUserId();
        if (empty($user_id)) {
            return response()->json([
                'errcode' => -1,
                'message' => __('message.user.register.failure'),
            ]);
        }
        $api_token = hash_hmac('sha256', Str::random(64), env('APP_KEY'));
        $api_token_expires_at = Carbon::now(env('APP_TIMEZONE'))->addHours(env('TOKEN_EXPIRES', 8));

        DB::beginTransaction();
        try {
            // 客户主帐号
            $user = new User();
            $user->id = $user_id;
            $user->email = $request->email;
            $user->username = 'IPX' . $user_id . '@ipxproxy.com';
            $user->password = Hash::make($request->password);
            $user->invite_userid = $invite_userid ?? 0;
            $user->api_token = $api_token;
            $user->api_token_expires_at = $api_token_expires_at;
            $user->channel_key = $request->input('channel_key', '');
            $user->channel_value = $request->input('channel_value', '');
            if (!$user->save()) {
                DB::rollBack();
                return response()->json([
                    'errcode' => -1,
                    'message' => __('message.user.register.failure'),
                ]);
            }

            // 客户子帐号
            $username = 'IPX' . $user->id;
            $proxyUser = new ProxyUser();
            $proxyUser->user_id = $user->id;
            $proxyUser->username = $username;
            $proxyUser->save();
            if (!$proxyUser->save()) {
                return response()->json([
                    'errcode' => -1,
                    'message' => __('message.user.register.failure'),
                ]);
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'errcode' => -1,
                'message' => __('message.user.register.failure'),
            ]);
        }

        // 创建IPWeb客户帐号
        dispatch(new AddIPWebCustomer($user->id));

        // 验证码过期
        Cache::forget($cache_key);

        $ip = $request->header('X-Real-IP') ?? $request->ip();
        $userAgent = $request->header('User-Agent');
        $isMobileDevice = preg_match('/(android|iphone|ipod|blackberry|windows phone)/i', $userAgent);

        $clickLog = ClickLog::create([
            'user_id' => $user->id,
            'ip' => $ip,
            'event_type' => 'login',
            'is_mobile' => (bool)$isMobileDevice,
            'user_agent' => $userAgent,
            'create_day' => date('Y-m-d'),
        ]);
        event(new ClickLogEvent($clickLog));

        return response()->json([
            'errcode' => 0,
            'message' => __('message.user.register.success'),
            'token' => $api_token
        ]);
    }

    /**
     * 退出
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout(Request $request)
    {
        $user = auth()->user();
        $user->api_token = '';
        $user->save();

        return response()->json([
            'errcode' => 0,
            'message' => __('message.user.logout.success')
        ]);
    }

    /**
     * 用户信息
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function info(Request $request)
    {
        $user = auth()->user();
        $config = Config::select('usdt_address', 'usdt_qrcode', 'alipay_switch')->first();
        $config->usdt_switch = 1;
        $config->credit_card = 1;

        $valid_count = StaticProxyDetail::where('status', '!=', 0)->where('user_id', $user['id'])->count();
        $soon_expire_count = StaticProxyDetail::where('status', 2)->where('user_id', $user['id'])->count();

        $data = [
            'id' => $user['id'],
            'is_admin' => $user['id'] == 100000 ? true : false,
            'is_distributor' => $user['is_distributor'] == 1 ? true : false,
            'email' => $user['email'],
            'traffic' => $user['traffic'],
            'total_traffic' => $user['total_traffic'],
            'consume_traffic' => $user['consume_traffic'],
            'static_proxy' => [
                'valid_count' => $valid_count,
                'soon_expire_count' => $soon_expire_count
            ],
            'created_at' => Carbon::parse($user['created_at'])->setTimezone(env('APP_TIMEZONE'))->format('Y-m-d H:i:s'),
            'pay_config' => $config
        ];
        return response()->json([
            'errcode' => 0,
            'data' => $data
        ]);
    }

    /**
     * 用户信息
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function changePass(Request $request)
    {
        $user = auth()->user();
        $validator = Validator::make($request->all(),
            [
                'password' => 'required|current_password:api',
                'new_password' => 'required|confirmed',
                'new_password_confirmation' => 'required|same:new_password',
            ]
        );
        if ($validator->fails()) {
            return response()->json([
                'errcode' => -1,
                'errmsg' => $validator->errors()->first(),
            ]);
        }

        $user->password = Hash::make($request->new_password);
        $user->api_token = '';
        $user->save();

        return response()->json([
            'errcode' => 0,
            'errmsg' => __('login.success')
        ]);
    }
}
